import Model from "./Model";
import Controller from "./Controller";

export default class View {

    ////////////////////////////////////////////////////////////////////////////
    //  constructor
    ////////////////////////////////////////////////////////////////////////////
    constructor(name, viewComponent) {
        this.eventList = [];
        if (name === undefined || name === '') {
            throw new Error('View name can not undefined!');
        }
        if (View.retrieveView(name) != null) {
            throw new Error('View[' + name + '] instance already constructed !');
        }
        this.name = name;
        this.viewComponent = viewComponent;
        this.eventList = this.listEventInterests();
        View.viewList.push(this);
        this.onRegister();
    }
    ////////////////////////////////////////////////////////////////////////////
    //  public static methods
    ////////////////////////////////////////////////////////////////////////////

    static retrieveView(name) {
        var len = View.viewList.length;
        for (var i = 0; i < len; ++i) {
            if (View.viewList[i].name === name) {
                return View.viewList[i];
            }
        }
        return null;
    }

    static removeView(name) {
        var len = View.viewList.length;
        for (var i = 0; i < len; ++i) {
            if (View.viewList[i].name === name) {
                View.viewList[i].onRemove();
                View.viewList[i].viewComponent = null;
                View.viewList[i].eventList = null;
                View.viewList[i] = null;
                View.viewList.splice(i, 1);
                break;
            }
        }
    }

    static removeViews(...argArray) {
        var len = argArray.length;
        for (var i = 0; i < len; ++i) {
            View.removeView(argArray[i]);
        }
    }

    static removeAllView(...exception) {
        var len = View.viewList.length;
        for (var i = len - 1; i >= 0; i--) {
            if (exception.indexOf(View.viewList[i].name) === -1) {
                View.viewList[i].onRemove();
                View.viewList[i].viewComponent = null;
                View.viewList[i].eventList = null;
                View.viewList[i] = null;
                View.viewList.splice(i, 1);
            }
        }
    }

    static notifyViews(type, data = null, sponsor = null) {
        var len = View.viewList.length;
        var motifyList = [];
        for (var i = 0; i < len; ++i) {
            var eventLen = View.viewList[i].eventList.length;
            for (var k = 0; k < eventLen; ++k) {
                if (View.viewList[i].eventList[k] === type) {
                    motifyList.push(View.viewList[i]);
                }
            }
        }
        for (var j = 0; j < motifyList.length; j++) {
            motifyList[j].handleEvent(type, data, sponsor);
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    //  public methods
    ////////////////////////////////////////////////////////////////////////////

    onRegister() {
        // overwrite
    }

    onRemove() {
        // overwrite
    }

    listEventInterests() {
        return [];
    }

    handleEvent(type, data = null, sponsor = null) {
        // overwrite
    }

    sendEvent(type, data = null, strict = false) {
        if (!strict) {
            Controller.notifyControllers(type, data, this);
        }
        View.notifyViews(type, data, this);
    }

    registerView(name, viewClass, viewComponent) {
        return new viewClass(name, viewComponent);
    }

    retrieveView(name) {
        return View.retrieveView(name);
    }

    retrieveModel(name) {
        return Model.retrieveModel(name);
    }
}

////////////////////////////////////////////////////////////////////////////
// protected static property
////////////////////////////////////////////////////////////////////////////
View.viewList = [];